<template>
    <div>
        <a-button type="primary" danger @click="handleOpenUploadModal" v-iscan="auth">上传附件</a-button>
        <a-modal v-model:open="UploadModalVisible" title="上传附件" wrapClassName="full-modal" width="100%" :okText="`全部上传 (${tableData.length})`" @ok="handleAllUpload">
            <a-spin :spinning="loading" tip="文件解析中...">
                <a-upload-dragger v-model:file-list="value" :directory="false" :before-upload="beforeUpload" multiple name="files" :maxCount="count" :showUploadList="false">
                    <p class="ant-upload-drag-icon">
                        <inbox-outlined></inbox-outlined>
                    </p>
                    <p class="ant-upload-text">Click or drag file to this area to upload</p>
                    <p class="ant-upload-hint">
                        Support for a single or bulk upload. Strictly prohibit from uploading company data or other
                        band files
                    </p>
                </a-upload-dragger>
                <iTable :pagination="false" :columns="columns" :tableData="tableData" :y="300">
                    <template #state="{ record }">
                        <a-tag v-if="record.state == 0" color="green">待上传</a-tag>
                        <a-tag v-if="record.state == 1" color="orange">上传中</a-tag>
                        <a-tag v-if="record.state == 2" color="blue">上传成功</a-tag>
                    </template>
                    <template #category="{ record }">
                        <a-select v-model:value="record.category" style="width: 120px">
                            <a-select-option v-for="(item,index) in CategoryData" :key="index" :value="item.value">{{ item.title }}</a-select-option>
                        </a-select>
                    </template>
                    <template #operate="{ record, index }">
                        <a-space :size="8">
                            <a-button type="link" @click="handleUpload(record)">开始上传</a-button>
                            <iDelete @delete="handleDelete(index)"></iDelete>
                        </a-space >
                    </template>
                </iTable>
            </a-spin>
        </a-modal>
    </div>
</template>

<script setup lang="ts">
import { GetToken } from '@/tool/common';
import { FileCut, FileSize, FileHash } from '@/tool/files';
import type { TableColumnsType } from 'ant-design-vue';
import axios from 'axios';
import { onMounted, ref } from 'vue';

import { useStore } from '@/stores/index'
const store = useStore()
const CategoryData = ref<any>()

const UploadModalVisible = ref<boolean>(false)
const handleOpenUploadModal = () => {
    tableData.value = []
    UploadModalVisible.value = true
}
const value = defineModel('value')
const props = defineProps<{
    count?: {
        type: number,
        default: 1
    },
    category: string,
    auth?: []
}>()

interface tableDataInterface {
    name: string
    size: string
    type: string
    hash: string
    category: string
    state: any
    file: File
    chunks: any
}

const tableData = ref<Array<tableDataInterface>>([])

const emit = defineEmits(['change'])

const handleDelete = (index: number) => {
    tableData.value.splice(index, 1)
}

const loading = ref<boolean>(false)

const handleAllUpload = () => {
    if(loading.value) {
        return
    }
    loading.value = true
    for(let i in tableData.value) {
        let item = tableData.value[i]
        if(item.state != 0) {
            return
        }
        handleUpload(item)
    }
    setTimeout(() => {
        UploadModalVisible.value = false
        loading.value = false
        emit("change")
    }, 1500)
}

const handleUpload = async (record: tableDataInterface) => {
    const init = await UploadInit(record) as any
    record.state = 1
    if (init.data.state == 0) {
        const chunk = await UploadChunk(record)
        if (chunk == record.chunks.length) {
            const merge = await UploadMerge(record) as any
            if (merge.code == 0) {
                record.state = 2
            }
        }
    }
    record.state = 2
}

const UploadMerge = async (record: tableDataInterface) => {
    return new Promise((resolve) => {
        const formData = new FormData();
        formData.append('hash', record.hash);
        const action = "/storage/UploadMerge"
        const config = {
            method: 'post',
            url: action,
            data: formData,
            headers: {
                "Content-Type": "multipart/form-data;",
                "Authorization ": GetToken()
            }
        }
        axios(config).then((_result: any) => {
            resolve(_result.data)
        })
    })
}

const UploadChunk = async (record: tableDataInterface) => {
    return new Promise((resolve) => {
        let finsh = 0
        for(let i = 0; i < record.chunks.length; i++) {
            let item = record.chunks[i]
            const formData = new FormData();
            formData.append('hash', record.hash);
            formData.append('chunk_hash', item.hash);
            formData.append('chunk', item.blob);
            formData.append('index', item.index);
            const action = "/storage/UploadChunk"
            const config = {
                method: 'post',
                url: action,
                data: formData,
                headers: {
                    "Content-Type": "multipart/form-data;",
                    "Authorization ": GetToken()
                }
            }
            axios(config).then((_result: any) => {
                if(_result.data.code === 0) {
                    finsh = finsh + 1
                }
                if(finsh == record.chunks.length) {
                    resolve(finsh)
                }
            })
        }
    })
}


const UploadInit = async (record: tableDataInterface) => {
    return new Promise((resolve) => {
        const formData = new FormData();
        formData.append('hash', record.hash);
        formData.append('category', record.category);
        formData.append('original_name', record.name);
        const file = record.file
        formData.append('file_size', file.size.toString());
        formData.append('file_type', record.type);
        const name = record.name as any
        formData.append('suffix', name.split('.').pop());
        const action = "/storage/UploadInit"
        const config = {
            method: 'post',
            url: action,
            data: formData,
            headers: {
                "Content-Type": "multipart/form-data;",
                "Authorization ": GetToken()
            }
        }
        axios(config).then((_result: any) => {
            resolve(_result.data)
        })
    })
}


const beforeUpload = async (file: File) => {
    loading.value = true
    var hash = await FileHash(file) as string
    const chunk = await FileCut(file)
    var obj: tableDataInterface = {
        name: file.name,
        size: FileSize(file.size),
        type: file.type,
        hash: hash,
        state: 0,
        category: props.category,
        file: file,
        chunks: chunk
    }
    tableData.value.push(obj)
    loading.value = false
    return false
}



const columns:TableColumnsType = [
    {
        title: "附件名称",
        dataIndex: "name",
        ellipsis: true
    },
    {
        title: "附件大小",
        dataIndex: "size",
    },
    {
        title: "附件类型",
        dataIndex: "type",
    },
    {
        title: "附件分类",
        dataIndex: "category",
    },
    {
        title: "状态",
        dataIndex: "state",
    },
    {
        title: "操作",
        dataIndex: "operate",
        width: 300,
    }
]

onMounted(() => {
    let category = store.Config.attachment_category
    CategoryData.value = [
        {
            title: "不分配",
            value: ""
        }
    ].concat(category)
})
</script>

<style lang="less" scoped>
  
</style>